function Vue(options) {
  this._init(options);
  this.$mount();
}
Vue.prototype._init = function (options) {
  let vm = this;
  vm.$options = options;
  if (options.props) {
    initPorps();
  }
  if (options.methods) {
    initMethods();
  }
  if (options.data) {
    initData(vm);
  }
  if (options.computed) {
    initComputed(vm);
  }
  if (options.watch) {
    initWatch(vm);
  }
};

Vue.prototype.$mount = function () {
  const vm = this;
  new Watcher(
    vm,
    vm.$options.render,
    () => {
      console.log("渲染函数的回调");
    },
    {}
  );
};
Vue.prototype.$watch = function (Vue, exprOrfn, handler, options = {}) {
  let watcher = new Watcher(Vue, exprOrfn, handler, {
    ...options,
    user: true,
  });

  if (options.immediate) {
    handler.call(Vue);
  }
};
function initPorps() {}
function initMethods() {}
function initData(vm) {
  let data = vm.$options.data;
  console.log(vm);
  data = vm._data = typeof data === "function" ? data.call(vm) : data;
  for (const key in data) {
    proxy(vm, "_data", key);
  }
  observe(data);
}
function proxy(target, source, key) {
  Object.defineProperty(target, key, {
    get() {
      return target[source][key];
    },
    set(newVal) {
      if (newVal === target[source][key]) return;
      target[source][key] = newVal;
    },
  });
}
// 初始化computed
function initComputed(vm) {
  // 拿到实例上传递computed
  let computed = vm.$options.computed;
  // 需要一个watcher
  let watcher = (vm._computedWatchers = {});
  // 将computed通过defineProperty 进行处理
  for (const key in computed) {
    // 注意有两种方式的处理 1:addAge(){} 2:addAge:{get(),set()}
    let userDef = computed[key];
    // 获取到get
    let getter = typeof userDef === "function" ? userDef : userDef.get;
    // 给计算属性中的每一个属性都要添加一个watcher。 lazy代表的是计算属性，初始化的时候不自动调用
    watcher[key] = new Watcher(vm, getter, () => {}, { lazy: true });
    defineComputed(vm, key, userDef);
  }
}
let sharedPropDefinition = {};
function defineComputed(target, key, userDef) {
  sharedPropDefinition = {
    enumerable: true,
    configurable: true,
    get() {},
    set() {},
  };
  if (typeof userDef == "function") {
    sharedPropDefinition.get = createComputedGetter(key);
  } else {
    sharedPropDefinition.get = createComputedGetter(key);
    sharedPropDefinition.set = userDef.set;
  }
  Object.defineProperty(target, key, sharedPropDefinition);
}

// 返回的是用户的方法
function createComputedGetter(key) {
  return function () {
    let watcher = this._computedWatchers[key];
    if (watcher) {
      if (watcher.dirty) {
        // 执行computed的逻辑
        // 它是在watcher上重新定义了一个方法.evaluate方法中的就是this.get()
        watcher.evaluate();
      }
      // 判断有没有渲染watcher
      if (Dep.target) {
        // 说明还有渲染watcher
        // depend函数会把刚才计算属性watcher添加的deps也添加到render watcher中去
        watcher.depend();
      }
      return watcher.value;
    }
  };
}
function initWatch(vm) {
  let watch = vm.$options.watch;
  for (const key in watch) {
    let handler = watch[key];
    if (Array.isArray(handler)) {
      //数组
      handler.forEach((item) => {
        createrWatcher(vm, key, item);
      });
    } else {
      // 对象/字符串/函数
      createrWatcher(vm, key, handler);
    }
  }
}
function createrWatcher(vm, exprOrfn, handler, options) {
  if (typeof handler == "object") {
    options = handler; //用户的配置项目
    handler = handler.handler; // 这是一个函数
  }

  if (typeof handler == "string") {
    handler = vm[handler];
  }

  return vm.$watch(vm, exprOrfn, handler, options);
}
